package com.rectcircle.scalatrateset.auth.strategies

import javax.servlet.http.{HttpServletRequest, HttpServletResponse}

import com.rectcircle.scalatrateset.model.User
import org.scalatra.{CookieOptions, ScalatraBase}
import org.scalatra.auth.ScentryStrategy

/**
  * Created by sunben960729 on 2016/12/30.
  */
class RememberMeStrategy(protected val app: ScalatraBase)(implicit request: HttpServletRequest, response: HttpServletResponse)
  extends ScentryStrategy[User] {
	
	//定义策略名
	override def name: String = "RememberMe"
	
	//储存token的cookies的key
	val COOKIE_KEY = "rememberMe"
	//cookie有效期
	private val oneWeek = 7 * 24 * 3600
	
	/**
	  * 抓取根据cookieKey从cookie中获取token的值。
	  * 如果存在就返回字符串
	  * 否则返回空字符串
	  */
	private def tokenVal = {
		app.cookies.get(COOKIE_KEY) match {
			case Some(token) => token
			case None => ""
		}
	}
	
	/***
	  * 确定当前策略是否应为当前请求运行
	  * 是数据检验
	  */
	override def isValid(implicit request: HttpServletRequest):Boolean = {
		tokenVal != ""
	}
	
	/***
	  * 在真实的项目中，我们会检查cookie的令牌值是否和储存在数据库中（或缓存中）已知哈希，看看是否要接受。
	  * 在测试中以一个固定字符串代替
	  */
	override def authenticate()(implicit request: HttpServletRequest, response: HttpServletResponse): Option[User] = {
		if(tokenVal == "foobar") Some(new User("foo","foo"))
		else None
	}
	
	/**
	  * 如果用户目前没有验证，应该发生什么？
	  * 也就是说，用户未登陆，一般跳转到登陆页面
	  */
	override def unauthenticated()(implicit request: HttpServletRequest, response: HttpServletResponse) {
		app.redirect("/login")
	}
	
	/***
	  *
	  * 在认证成功后执行；
	  * if(在本策略认证成功||(在验证密码认证成功&&勾选了记住我)){
	  *   设定记住登录状态的cookies，写回客户端
	  * }
	  *
	  */
	override def afterAuthenticate(winningStrategy: String, user: User)(implicit request: HttpServletRequest, response: HttpServletResponse) = {
		if (winningStrategy == "RememberMe" ||
		  (winningStrategy == "UserLogin" && checkbox2boolean(app.params.get("rememberMe").getOrElse("").toString))) {
			val token = "foobar"
			app.cookies.set(COOKIE_KEY, token)(CookieOptions(maxAge = oneWeek, path = "/"))
		}
	}
	
	/**
	  * 在之前注销运行此代码，清理任何遗留数据库状态和删除Cookie记得登录状态的token。
	  */
	override def beforeLogout(user: User)(implicit request: HttpServletRequest, response: HttpServletResponse) = {
		app.cookies.delete(COOKIE_KEY)(CookieOptions(path = "/"))
	}
	
	/**
	  * 用于容易地匹配一个复选框的值
	  */
	private def checkbox2boolean(s: String): Boolean = {
		s match {
			case "yes" => true
			case "y" => true
			case "1" => true
			case "true" => true
			case _ => false
		}
	}
	
}
